package com.gitee.apanlh.util.base;

import com.gitee.apanlh.exp.CallRuntimeException;
import com.gitee.apanlh.util.func.FuncCall;
import com.gitee.apanlh.util.func.FuncExecute;
import com.gitee.apanlh.util.func.FuncIteratorResultE;

import java.util.Iterator;
import java.util.LinkedList;

/**
 * 	选择或条件对象
 * 	<br>此类可以用于简化多个if-elseif-else
 *
 * 	@author Pan
 */
public class ChooseOr<V> extends AbstractChoose<V> {

	/** 是否存在else表达式 */
	private boolean hasElse;
	/** 选择 */
	private LinkedList<ChooseOr<V>> chooses;
	/** 是否终止 */
	private boolean hasMatch;

	/**
	 * 	默认构造函数
	 * 
	 * 	@author Pan
	 */
	ChooseOr() {
		super();
	}
	
	/**	
	 * 	构造函数-初始化条件对象
	 * 	<br>验证条件结果为Ture返回Value
	 * 
	 * 	@author Pan
	 * 	@param 	condition	条件
	 * 	@param 	v			对象
	 */
	public ChooseOr(boolean condition, V v) {
		super(condition, v);
		initMatch(condition);
	}
	
	/**	
	 * 	构造函数-初始化条件对象
	 * 	<br>验证条件结果为Ture返回Value
	 * 	<br>将不会初始化结果状态
	 * 	
	 * 	@author Pan
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 */
	public ChooseOr(boolean condition, FuncCall<V> func) {
		super(condition, func);
		initMatch(condition);
	}

	/**
	 * 	构造函数-初始化条件对象
	 * 	<br>验证条件结果为Ture返回Value
	 * 	<br>将不会初始化结果状态
	 *
	 * 	@author Pan
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 */
	public ChooseOr(boolean condition, FuncExecute func) {
		super(condition, func);
		initMatch(condition);
	}

	/**
	 * 	初始化匹配条件
	 *
	 * 	@author Pan
	 * 	@param 	condition	条件
	 */
	private void initMatch(boolean condition) {
		if (condition) {
			this.hasMatch = true;
		}
		this.chooses = (LinkedList<ChooseOr<V>>) CollUtils.newLinkedList(this);
	}
	
	/**	
	 * 	构造函数-添加条件对象
	 * 	<br>验证条件结果为Ture返回Value
	 * 	
	 * 	@author Pan
	 * 	@param 	add			是否添加条件
	 * 	@param 	hasElse		是否Else条件对象
	 * 	@param 	condition	条件
	 * 	@param 	v			对象
	 */
	ChooseOr(boolean add, boolean hasElse, boolean condition, V v) {
		super(condition, v);
		this.hasElse = hasElse;
	}
	
	/**	
	 * 	构造函数-添加条件对象
	 * 	<br>验证条件结果为Ture返回Value
	 * 	<br>将不会初始化结果状态
	 * 	
	 * 	@author Pan
	 * 	@param 	add			是否添加条件
	 * 	@param 	hasElse		是否Else条件对象
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 */
	ChooseOr(boolean add, boolean hasElse, boolean condition, FuncCall<V> func) {
		super(condition, func);
		this.hasElse = hasElse;
	}

	/**
	 * 	构造函数-添加条件对象
	 * 	<br>验证条件结果为Ture返回Value
	 * 	<br>将不会初始化结果状态
	 *
	 * 	@author Pan
	 * 	@param 	add			是否添加条件
	 * 	@param 	hasElse		是否Else条件对象
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 */
	ChooseOr(boolean add, boolean hasElse, boolean condition, FuncExecute func) {
		super(condition, func);
		this.hasElse = hasElse;
	}

	/**	
	 * 	构建-或条件选择
	 * 	<br>函数式的构建方法
	 * 	
	 * 	@author Pan
	 * 	@param 	condition	条件
	 * 	@param 	value		回调对象
	 * 	@return	V
	 */
	public ChooseOr<V> orElseIf(boolean condition, V value) {
		if (hasMatch) {
			return this;
		}
		add(new ChooseOr<>(true, false, condition, value));
		return this;
	}
	
	/**	
	 * 	构建-或条件选择
	 * 	<br>函数式的构建方法
	 * 	
	 * 	@author Pan
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 * 	@return	V
	 */
	public ChooseOr<V> orElseIf(boolean condition, FuncCall<V> func) {
		if (hasMatch) {
			return this;
		}
		add(new ChooseOr<>(true, false, condition, func));
		return this;
	}

	/**
	 * 	构建-或条件选择
	 * 	<br>函数式的构建方法
	 *
	 * 	@author Pan
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 * 	@return	V
	 */
	public ChooseOr<V> orElseIf(boolean condition, FuncExecute func) {
		if (hasMatch) {
			return this;
		}
		add(new ChooseOr<>(true, false, condition, func));
		return this;
	}

	/**
	 * 	构建-或条件选择
	 * 	<br>value会被初始化加载，如果验证结果都需要实例对象情况下，使用函数式的构建方法
	 * 	
	 * 	@author Pan
	 * 	@param 	value		实例对象
	 * 	@return	V
	 */
	public V orElse(V value) {
		V choose = getChoose();
		if (choose == null) {
			return value;
		}
		return choose;
	} 
	
	/**	
	 * 	构建-或条件选择
	 * 	<br>函数式的构建方法
	 * 	
	 * 	@author Pan
	 * 	@param 	func		回调对象
	 * 	@return	V
	 */
	public V orElse(FuncCall<V> func) {
		V choose = getChoose();
		if (choose == null) {
			try {
				return func.call();
			} catch (Exception e) {
				throw new CallRuntimeException(e.getMessage(), e);
			}
		}
		return choose;
	}

	/**
	 * 	构建-或条件选择
	 * 	<br>函数式的构建方法
	 *
	 * 	@author Pan
	 * 	@param 	func		回调对象
	 */
	public void orElse(FuncExecute func) {
		V choose = getChoose();
		if (choose == null) {
			try {
				func.execute();
			} catch (Exception e) {
				throw new CallRuntimeException(e.getMessage(), e);
			}
		}
	}

	/**
	 * 	构建-或条件选择
	 * 	<br>抛出运行时异常
	 * 	
	 * 	@author Pan
	 * 	@param 	exp	自定义运行异常对象
	 * 	@return	RuntimeException
	 * 	@throws RuntimeException	自定义运行时异常抛出 
	 */
	public V orElse(RuntimeException exp) {
		V choose = getChoose();
		if (choose == null) {
			throw exp;
		}
		return choose;
	} 
	
	/**	
	 * 	获取选择返回true的结果
	 * 	
	 * 	@author Pan
	 * 	@return	V
	 */
	public V getChoose() {
		return IteratorUtils.collectionResult(this.chooses, new FuncIteratorResultE<ChooseOr<V>, V>() {
			V v = null;
			@Override
			public boolean next(ChooseOr<V> e, Iterator<ChooseOr<V>> iterator) {
				if (e.getCondition()) {
					v = e.getValue();
					return false;
				}
				return true;
			}
			@Override
			public V call() {
				return v;
			}
		});
	}
	
	/**	
	 * 	添加或条件对象
	 * 	
	 * 	@author Pan
	 * 	@param 	chooseOr	或对象	
	 */
	void add(ChooseOr<V> chooseOr) {
		if (hasMatch) {
			return ;
		}
		if (chooseOr.hasElse()) {
			this.chooses.addLast(chooseOr);
		} else {
			this.chooses.add(chooseOr);
		}
	}

	/**	
	 * 	是否存在else表达式
	 * 	
	 * 	@author Pan
	 * 	@return	boolean
	 */
	boolean hasElse() {
		return hasElse;
	}
	
	/**
	 * 	构建-或条件选择
	 * 	<br>value会被初始化加载，如果验证结果都需要实例对象情况下，使用函数式的构建方法
	 * 	
	 * 	@author Pan
	 * 	@param 	<V>			值类型
	 * 	@param 	condition	条件
	 * 	@param 	value		实例对象
	 * 	@return	V
	 */
	public static <V> ChooseOr<V> create(boolean condition, V value) {
		return new ChooseOr<>(condition, value);
	} 
	
	/**	
	 * 	构建-或条件选择
	 * 	<br>函数式的构建方法
	 * 	
	 * 	@author Pan
	 * 	@param 	<V>			值类型
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 * 	@return	V
	 */
	public static <V> ChooseOr<V> create(boolean condition, FuncCall<V> func) {
		return new ChooseOr<>(condition, func);
	}

	/**
	 * 	构建-或条件选择
	 * 	<br>函数式的构建方法
	 *
	 * 	@author Pan
	 * 	@param 	<V>			值类型
	 * 	@param 	condition	条件
	 * 	@param 	func		回调对象
	 * 	@return	V
	 */
	public static <V> ChooseOr<V> create(boolean condition, FuncExecute func) {
		return new ChooseOr<>(condition, func);
	}

}
